package battle

import (
	"fmt"
	"server/game/cache"
	"server/game/itypes"
	"server/game/model"
	"server/share/config"

	"github.com/hwcer/cosgo/registry"
	"github.com/hwcer/cosgo/slice"
	"github.com/hwcer/yyds/context"
	"github.com/hwcer/yyds/errors"
)

func init() {
	Register(&mainStory{})
}

//const MainStoryMiddlewareName = "MainStoryMiddlewareName"
//
//type MainStoryMiddlewareStruct struct {
//	Chapter int32 `json:"id"` //chapterID
//	Stage   int32 `json:"stageID"`
//	next    bool
//}
//
//func (this *MainStoryMiddlewareStruct) Emit(updater *updater.Updater, t updater.EventType) bool {
//	return this.next
//}

type mainStory struct {
}

func (this *mainStory) Caller(node *registry.Node, handle *context.Context) interface{} {
	f := node.Method().(func(*mainStory, *context.Context) interface{})
	return f(this, handle)
}

/**
 * @name getMainStoryData
 * 获取主线剧情的历史信息
 */
func (this *mainStory) GetMainStoryData(c *context.Context) interface{} {
	var rows []*model.Chapter
	if tx := db.Find(&rows, "uid = ?", c.Uid()); tx.Error != nil {
		return tx.Error
	}
	r := make(map[string]interface{})
	for _, row := range rows {
		r[row.OID] = row
	}
	return r
}

/**
 * @name startMainStory
 * @param int id 关卡ID
 * 创建主线战斗
 */
func (this *mainStory) StartMainStory(c *context.Context) any {
	id := c.GetInt32("id")
	if id <= 0 {
		return errors.ErrArgEmpty
	}
	chapterID := id / 100
	arr := []int32{chapterID}
	mainChapterConfig := config.Data.MainChapter[chapterID]
	if mainChapterConfig == nil {
		return errors.ErrConfigEmpty
	}
	mainNodeConfig := config.Data.MainNode[id]
	if mainNodeConfig == nil {
		return errors.ErrConfigEmpty
	}
	var frontChapterID int32
	if mainNodeConfig.Front > 0 {
		frontChapterID = mainNodeConfig.Front / 100
		if frontChapterID != chapterID {
			arr = append(arr, frontChapterID)
		}
	}

	var rows []*model.Chapter
	if tx := db.Where("uid = ?", c.Uid()).Find(&rows, "iid IN ?", arr); tx.Error != nil {
		return tx.Error
	}
	chapter := map[int32]*model.Chapter{}
	for _, row := range rows {
		chapter[row.IID] = row
	}
	if frontChapterID > 0 {
		frontChapter := chapter[frontChapterID]
		if frontChapter == nil {
			return c.Error("frontChapter not pass")
		}
		frontStage := frontChapter.Stage[mainNodeConfig.Front]
		if frontStage == nil || frontStage.Pass == 0 {
			return c.Error("frontChapter not pass")
		}
	}
	data := chapter[chapterID]
	if data == nil {
		if i, err := itypes.Chapter.Create(c.Player.Updater, chapterID, 1); err != nil {
			return err
		} else {
			data = i.(*model.Chapter)
		}

	}

	mw := &Middleware{}
	mw.Create(c.Player, MiddlewareTypeMainStory, id, nil)

	return data

}

/**
 * @name endMainStory
 * @param json data 通关数据
 * 结算主线战斗
 */

func (this *mainStory) EndMainStory(c *context.Context) any {
	var req = struct {
		Data map[string]int32 `json:"data"`
	}{
		Data: map[string]int32{},
	}

	if err := c.Bind(&req); err != nil {
		return err
	}
	args := req.Data

	//var mainStoryCache *Middleware
	//if i := c.Player.Updater.Events.Get(MiddlewareName); i == nil {
	//	return c.Error("mainStoryCache empty")
	//} else {
	//	mainStoryCache = i.(*Middleware)
	//}
	//if mainStoryCache.T != MiddlewareTypeMainStory {
	//	return c.Error("mainStoryCache error")
	//}
	mw := &Middleware{}
	if !mw.Verify(c.Player, MiddlewareTypeMainStory, 0) {
		return c.Error("battle error")
	}
	stageId := mw.K

	chapterId := stageId / 100
	chapter := c.Player.Collection(config.ITypeChapter)
	chapter.Select(chapterId)
	if err := c.Player.Data(); err != nil {
		return err
	}
	var data *model.Chapter
	i := chapter.Get(chapterId)
	if i == nil {
		i, _ = itypes.Chapter.Create(c.Player.Updater, chapterId, 1)
	}
	data = i.(*model.Chapter)

	mainNodeConfig := config.Data.MainNode[stageId]
	if mainNodeConfig == nil {
		return errors.ErrConfigEmpty
	}
	var score int32
	for _, k := range mainNodeConfig.ScoreRequire {
		scoreConfig := config.Data.ScoreRequire[k]
		if scoreConfig == nil {
			return c.Error("scoreConfig empty")
		}
		if scoreConfig.Compare == 0 {
			if args[scoreConfig.Key] >= scoreConfig.Val {
				score++
			}
		} else if scoreConfig.Compare == 1 {
			if args[scoreConfig.Key] <= scoreConfig.Val {
				score++
			}
		} else {
			return c.Error("scoreConfig Compare error")
		}
	}
	stage := data.Stage[stageId]
	if stage == nil {
		stage = &model.Stage{}
		data.Stage[stageId] = stage
	}
	if stage.Pass == 0 {
		//首通
		stage.Pass = 1
		stage.Score = score
		roleDoc := cache.GetRole(c.Player.Updater)
		roleDoc.Add("hangPoint", 1)
		c.Player.AddItems(mainNodeConfig.ItemDrop)
	} else {
		c.Player.Add(mainNodeConfig.Box, mainNodeConfig.Count)
		if score > stage.Score {
			stage.Score = score
		}
	}
	stage.Data = args

	key := fmt.Sprintf("stageData.%d", stageId)
	chapter.Set(chapterId, key, stage)

	//if err := db.Select("stage").Update(data, data.OID).Error; err != nil {
	//	return err
	//}

	c.Player.Emit(config.Data.Events.MainStage, stageId)
	return nil
}

/**
 * @name getMainStoryReward
 * @param int id 章节ID
 * @param array rewardIDList 奖励ID列表
 * 领取主线剧情奖励
 */
func (this *mainStory) GetMainStoryReward(c *context.Context) any {
	id := c.GetInt32("id")
	if id <= 0 {
		return errors.ErrArgEmpty
	}
	mainChapterConfig := config.Data.MainChapter[id]
	if mainChapterConfig == nil {
		return errors.ErrConfigEmpty
	}

	chapter := c.Player.Collection(config.ITypeChapter)
	chapter.Select(id)
	if err := c.Player.Data(); err != nil {
		return err
	}
	var data *model.Chapter
	i := chapter.Get(id)
	if i == nil {
		i, _ = itypes.Chapter.Create(c.Player.Updater, id, 1)
	}
	data = i.(*model.Chapter)

	if tx := db.Find(data, data.OID); tx.Error != nil {
		return tx.Error
	} else if tx.RowsAffected == 0 {
		return errors.ErrDataNotExists
	}
	reward := data.Reward
	var score int32
	for _, s := range data.Stage {
		score += s.Score
	}
	var flag bool
	for k, v := range mainChapterConfig.ItemList {
		if score >= v.Score && !slice.Has(reward, int32(k)) {
			flag = true
			c.Player.Add(v.Id, v.Count)
			reward = append(reward, int32(k))
		}
	}
	if flag {
		chapter.Set(data.OID, "reward", reward)
	}
	return nil
}
